#include "kernel/driver/mousedriver.h"
#include "kernel/apic/apic.h"
#include "kernel/log/log.h"
#include "libs/lib.h"
#include "libs/io.h"


int MouseDriver::mouse_count = 0;

MouseDriver::MouseDriver(interruptmanager* interrupts):
interrupthandler(0x2c,interrupts)
{
#ifdef APIC
    IO_APIC_RET_entry entry;
    p_head = buf;
    p_tail = buf;
    count = 0;
    memset(buf,0,KB_BUF_SIZE);

    entry.vector = 0x2c;
	entry.deliver_mode = APIC_ICR_IOAPIC_Fixed ;
	entry.dest_mode = ICR_IOAPIC_DELV_PHYSICAL;
	entry.deliver_status = APIC_ICR_IOAPIC_Idle;
	entry.polarity = APIC_IOAPIC_POLARITY_HIGH;
	entry.irr = APIC_IOAPIC_IRR_RESET;
	entry.trigger = APIC_ICR_IOAPIC_Edge;
	entry.mask = APIC_ICR_IOAPIC_Masked;
	entry.reserved = 0;

	entry.destination.physical.reserved1 = 0;
	entry.destination.physical.phy_dest = 0;
	entry.destination.physical.reserved2 = 0;


    install(&entry);
    enable();


#endif
    //Open Mouse
    wait_KB_write();
	io_out8(PORT_KB_CMD,KBCMD_EN_MOUSE_INTFACE);

	for(uint64_t i = 0;i<1000;i++)
		for(uint64_t j = 0;j<1000;j++)
			nop();
        //配置mouse

	wait_KB_write();
	io_out8(PORT_KB_CMD,KBCMD_WRITE_CMD);
	wait_KB_write();
	io_out8(PORT_KB_DATA,KB_INIT_MODE);
	for(uint64_t i = 0;i<1000;i++)
		for(uint64_t j = 0;j<1000;j++)
			nop();

    //使能Mouse
    wait_KB_write();
    io_out8(PORT_KB_CMD,KBCMD_SENDTO_MOUSE);
    wait_KB_write();
    io_out8(PORT_KB_DATA,MOUSE_ENABLE);





}

MouseDriver::~MouseDriver()
{
#ifdef APIC
    disable();
    uninstall();

#endif
}


StackFrame* MouseDriver::handleInterrupt(StackFrame* fs){

   
    char x = io_in8(PORT_KB_DATA);
    if(p_head == buf + KB_BUF_SIZE)
        p_head = buf;
    *p_head = x;
    count++;
    p_head++;

}

uint8_t MouseDriver::getMouseCode(){

    uint8_t ret = 0;

    if(count == 0)
    {
        while (!count)
        {
            nop();
        }
    }
    if(p_tail == buf + KB_BUF_SIZE){

        p_tail = buf;

    } 

    ret = *p_tail;
    count--;
    p_tail++;

    return ret;


}


void MouseDriver::analysisMouseCode(){

    uint8_t x = getMouseCode();

    switch (mouse_count)
    {
		case 0:
			mouse_count++;
			break;

		case 1:
			mouse.Byte0 = x;
			mouse_count++;
			break;
		
		case 2:
			mouse.Byte1 = (char)x;
			mouse_count++;
			break;

		case 3:
			mouse.Byte2 = (char)x;
			mouse_count = 1;
			LOG_INFO("(M:%02x,X:%3d,Y:%3d)\n",mouse.Byte0,mouse.Byte1,mouse.Byte2);
			break;

		default:			
			break;
    }

    
}